Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds comprehensive LLM agent documentation for the Respo/Calcit project and implements a "thinking text" feature to display AI model reasoning separately from final answers. The changes include dependency updates, UI enhancements for streaming AI responses, and extensive developer guides.
Key Changes:
- Added thinking text support to separate AI reasoning from final answers in the UI
- Created two comprehensive documentation files for LLM agents (Agents.md and llms/Respo.md)
- Updated dependencies (@calcit/procs, @google/genai, openai, rolldown-vite, and others)
- Added accessibility controls for touch interactions and zoom prevention
Reviewed changes
Copilot reviewed 6 out of 8 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| compact.cirru | Core logic changes: added *thinking-text parameter to track AI reasoning separately, new style-thinking CSS, event handlers for touch/zoom control |
| yarn.lock | Updated all package versions and changed registry from yarnpkg.com to npmmirror.com (Chinese mirror) |
| package.json | Bumped versions for @calcit/procs (0.9.20→0.10.4), @google/genai (1.24.0→1.34.0), openai (6.3.0→6.15.0) |
| deps.cirru | Updated calcit-version (0.9.20→0.10.4) and respo.calcit (0.16.21→0.16.22) |
| Agents.md | New 445-line comprehensive guide for LLM agents working with Calcit CLI tools |
| llms/Respo.md | New 920-line development guide specifically for LLM agents building Respo applications |
| .gitattributes | Excluded new documentation files from diff and marked as linguist-generated |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| is-thinking? $ if (some? part) (.-thought part) false | ||
| t $ if (some? part) (.-text part) (.-text chunk) | ||
| let | ||
| text $ or t (-> chunk .?-promptFeedback .?-blockReason) |__BLANK__ |
There was a problem hiding this comment.
The hardcoded string value |__BLANK__ is used as a fallback when text is undefined. This is likely meant to be an empty string "" instead. Using |__BLANK__ will display literally as "BLANK" to users, which appears to be debug text rather than an intentional user-facing message.
| text $ or t (-> chunk .?-promptFeedback .?-blockReason) |__BLANK__ | |
| text $ or t (-> chunk .?-promptFeedback .?-blockReason) "\"" |
| js-object (:thinkingBudget 0) (:includeThoughts false) | ||
| :httpOptions $ js-object | ||
| :baseUrl $ get-env "\"gemini-host" "\"https://ja.chenyong.life" | ||
| :httpOptions $ js-object (:baseUrl |https://ja.chenyong.life) |
There was a problem hiding this comment.
The baseUrl has been changed from a string literal "https://ja.chenyong.life" to a symbol |https://ja.chenyong.life. In Cirru syntax, the | prefix denotes a string, which is correct. However, this appears in multiple places (lines 134, 203, 263) and should be consistent. Verify this is the intended format for all three occurrences.
| js/window.addEventListener |dblclick $ fn (event) (.!preventDefault event) | ||
| js/window.addEventListener |wheel | ||
| fn (event) | ||
| if (.-ctrlKey event) (.!preventDefault event) |
There was a problem hiding this comment.
The wheel event listener with passive: false is added to prevent zoom on Ctrl+wheel, but this approach has accessibility implications. Users who rely on browser zoom for accessibility may find this frustrating. Consider:
- Adding a user preference toggle for this behavior
- Only preventing zoom in specific UI areas rather than globally
- Documenting this behavior in user-facing documentation
| if (.-ctrlKey event) (.!preventDefault event) | |
| let | |
| target $ .-target event | |
| when | |
| and (.-ctrlKey event) | |
| some? $ .!closest target "\".app" | |
| .!preventDefault event |
| js/window.addEventListener |beforeunload $ fn (event) (persist-storage!) | ||
| js/window.addEventListener |visibilitychange $ fn (event) | ||
| if (= "\"hidden" js/document.visibilityState) (persist-storage!) | ||
| js/window.addEventListener |dblclick $ fn (event) (.!preventDefault event) |
There was a problem hiding this comment.
The double-click event handler prevents default behavior globally on the window, which will disable all text selection via double-click across the entire application. This is likely too broad and may harm user experience. Consider:
- Applying this only to specific elements (e.g., buttons, non-text areas)
- Using CSS
user-select: noneon specific elements instead - Removing this if not strictly necessary for the feature
| js/window.addEventListener |dblclick $ fn (event) (.!preventDefault event) |
| {} $ :max-width "\"90vw" | ||
| "\"&" $ {} (:color "\"#999") (:transition-duration "\"300ms") | ||
| :background-color $ hsl 0 0 98 | ||
| :touch-action :none |
There was a problem hiding this comment.
The CSS property touch-action: none completely disables touch interactions including scrolling on mobile devices. This creates a significant usability issue for mobile users who won't be able to interact with the UI element. Consider using more specific values like touch-action: pan-y or touch-action: manipulation to preserve essential touch interactions while preventing unwanted behaviors.
| :touch-action :none | |
| :touch-action :pan-y |
| :flash-imagen $ js-await (call-flash-imagen-msg! model cursor state prompt-text d!) | ||
| :imagen-4 $ js-await (call-imagen-4-msg! model cursor state prompt-text d!) | ||
| :gemini-thinking $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text) | ||
| :gemini-flash-thinking $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text) | ||
| :gemini-flash-lite $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text) | ||
| :gemini-flash $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text) | ||
| :gemini-learnlm $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text) | ||
| :gemini-thinking $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text) | ||
| :gemini-flash-thinking $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text) | ||
| :gemini-flash-lite $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text) | ||
| :gemini-flash $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text) | ||
| :gemini-learnlm $ js-await (call-genai-msg! model cursor state prompt-text search? think? d! *text *thinking-text) | ||
| :claude-3.7 $ js-await (call-anthropic-msg! cursor state prompt-text "\"claude-3-7-sonnet-20250219" false d!) | ||
| :openrouter/anthropic/claude-sonnet-4 $ js-await (call-openrouter! cursor state prompt-text "\"anthropic/claude-sonnet-4" true d! *text) | ||
| :openrouter/anthropic/claude-opus-4 $ js-await (call-openrouter! cursor state prompt-text "\"anthropic/claude-opus-4" true d! *text) |
There was a problem hiding this comment.
The function signature changed to add *thinking-text parameter, but the calls to call-anthropic-msg! and image-related functions in the submit-message! case statement do not pass this new parameter. This creates an inconsistency where only some model paths support thinking text tracking. Consider either:
- Adding thinking text support to all model handlers, or
- Making
*thinking-textoptional for backward compatibility
No description provided.